package org.example;

import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;

public class RetryTemplate {

    public static class ExhaustedRetryException extends RuntimeException {
    }


    public static void execute(int count, int delayTime, TimeUnit timeUnit, Runnable task) throws Exception {
        int i = 0;
        Exception exception = null;
        for (; i < count; i++) {
            try {
                System.out.println("retry " + (i + 1) + " times.");
                task.run();
                break;
            } catch (Exception e) {
                exception = e;
                handleException(delayTime, timeUnit);
            }
        }
        if (i == count && exception != null) {
            System.out.println("retry failed.");
            throw exception;
        }
    }

    public static <T> T execute(int count, int delayTime, TimeUnit timeUnit, Callable<T> task) throws Exception {
        int i = 0;
        Exception exception = null;
        for (; i < count; i++) {
            try {
                System.out.println("retry " + (i + 1) + " times.");
                return task.call();
            } catch (Exception e) {
                exception = e;
                handleException(delayTime, timeUnit);
            }
        }
        if (i == count && exception != null) {
            System.out.println("retry failed.");
            throw exception;
        }
        return null;
    }

    private static void handleException(int delayTime, TimeUnit timeUnit) {
        try {
            timeUnit.sleep(delayTime);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}
